feat(api): add canonical PolicyStatusSummary to workflow run list and describe#3061
Merged
migmartri merged 4 commits intochainloop-dev:mainfrom Apr 21, 2026
Merged
Conversation
… describe Adds a canonical, server-computed PolicyStatus enum (NOT_APPLICABLE, PASSED, SKIPPED, WARNING, BLOCKED, BYPASSED) and a PolicyStatusSummary (status + total/passed/skipped/violated counters) to both WorkflowRunItem and AttestationItem.PolicyEvaluationStatus. A single derivation helper feeds both list and describe paths. The summary is materialized on the workflow_run row at attestation-ingest time so the list handler stays an index scan. Also introduces a PolicyStatusFilter aligned 1:1 with the enum; the coarse PolicyViolationsFilter and the redundant evaluations_count / violations_count fields on PolicyEvaluationStatus are marked deprecated. Closes PFM-5616. Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>
Superseded by policy_summary.status (and policy_summary.violated > 0 for the coarse boolean case). Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>
There was a problem hiding this comment.
1 issue found across 34 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="pkg/attestation/renderer/chainloop/v02.go">
<violation number="1" location="pkg/attestation/renderer/chainloop/v02.go:487">
P2: Backfill skipped/passed counts for historic attestations before deriving the canonical status; otherwise old skipped-only envelopes are misclassified as PASSED.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.
…ations Attestations signed before the skipped/passed counters were added to the predicate decode them as zero. When inline evaluations are available, recompute at describe time so DerivePolicyStatusSummary doesn't misclassify skipped-only runs as PASSED. Identified by cubic. Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>
jiparis
reviewed
Apr 20, 2026
migmartri
commented
Apr 20, 2026
jiparis
approved these changes
Apr 21, 2026
Surfaces whether a run had gates in effect (any policy marked gate:true or contract using ENFORCED strategy) on both PolicyStatusSummary and WorkflowRunServiceListRequest. Independent of policy status — a PASSED run can still have has_gates=true. Materialized on workflow_run via a partial index so the list filter is cheap. Also refactored the renderer backfill for historic envelopes to a single pass that derives skipped/passed counts and gate presence together. Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>
There was a problem hiding this comment.
1 issue found across 28 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="pkg/attestation/renderer/chainloop/policy_status.go">
<violation number="1" location="pkg/attestation/renderer/chainloop/policy_status.go:72">
P2: Preserve `HasGates` for zero-evaluation statuses; this early return drops the flag for enforced-but-empty runs and makes them look identical to truly ungated rows.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.
| Passed: s.PassedCount, | ||
| Skipped: s.SkippedCount, | ||
| Violated: s.ViolationsCount, | ||
| HasGates: s.HasGates, |
There was a problem hiding this comment.
P2: Preserve HasGates for zero-evaluation statuses; this early return drops the flag for enforced-but-empty runs and makes them look identical to truly ungated rows.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At pkg/attestation/renderer/chainloop/policy_status.go, line 72:
<comment>Preserve `HasGates` for zero-evaluation statuses; this early return drops the flag for enforced-but-empty runs and makes them look identical to truly ungated rows.</comment>
<file context>
@@ -66,6 +69,7 @@ func DerivePolicyStatusSummary(s *PolicyEvaluationStatus) PolicyStatusSummary {
Passed: s.PassedCount,
Skipped: s.SkippedCount,
Violated: s.ViolationsCount,
+ HasGates: s.HasGates,
}
</file context>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a canonical, server-computed
PolicyStatusenum andPolicyStatusSummary(status + per-evaluation counters) to bothWorkflowRunItem(list response) andAttestationItem.PolicyEvaluationStatus(describe response), so the runs list can render a policy-status badge without fanning out oneViewcall per row. The summary is computed from a single backend helper shared by list and describe, and is materialized on theworkflow_runrow at attestation-ingest time to keep the list handler an index scan.PolicyStatusenum:NOT_APPLICABLE,PASSED,SKIPPED,WARNING,BLOCKED,BYPASSED. Enforcement (advisory vs enforced, gated, bypassed) is embedded in the enum — the raw bools remain on describe for fine-grained detail-page copy.PolicyStatusSummary { status, total, passed, skipped, violated }surfaced on both list and describe.PolicyStatusFilteronWorkflowRunService.List, aligned 1:1 with the status values. The existingPolicyViolationsFilterand theevaluations_count/violations_countfields onPolicyEvaluationStatusare preserved but marked[deprecated = true];has_policy_violationsis also preserved.workflow_run(policy_status,policy_evaluations_total,policy_evaluations_passed,policy_evaluations_skipped,policy_violations_count) plus an index onpolicy_status. Rows predating the change stayNULLand are interpreted as not-summarized (clients fall back tohas_policy_violations).Closes PFM-5616. Upstream prerequisite for platform spec 034 (eliminating the workflow-run describe fan-out on list views).
Test plan
make -C app/controlplane test-unitgreen (includes new 12-case table-driven test forDerivePolicyStatusSummaryand extendedTestPolicyEvaluationStatusCounts).make -C app/controlplane testgreen (full integration suite includingTestWorkflowRunUseCase).policy_summarypopulated on bothworkflow wf-run listandworkflow wf-run describe.PolicyStatusFilterreturns only runs in the requested state.